import { ICache } from '../interfaces/ICache';

/**
 * LRU缓存实现类
 */
export class LRUCache<K = string, V = any> implements ICache<K, V> {
    /** 缓存数据 Map<键, {值, 过期时间}> */
    private cache: Map<K, { value: V; expiry?: number }>;

    /** 最大缓存条目数 */
    private readonly maxItems: number;

    /** 默认过期时间（毫秒） */
    private readonly defaultTTL?: number;

    /**
     * 构造函数
     * @param maxItems 最大缓存条目数
     * @param defaultTTL 默认过期时间（毫秒）
     */
    constructor(maxItems: number = 1000, defaultTTL?: number) {
        this.cache = new Map();
        this.maxItems = maxItems;
        this.defaultTTL = defaultTTL;
    }

    /**
     * 获取缓存项
     * @param key 键
     */
    get(key: K): V | undefined {
        const item = this.cache.get(key);
        if (!item) return undefined;

        // 检查是否过期
        if (item.expiry && item.expiry < Date.now()) {
            this.cache.delete(key);
            return undefined;
        }

        // 更新访问顺序（LRU）
        this.cache.delete(key);
        this.cache.set(key, item);

        return item.value;
    }

    /**
     * 设置缓存项
     * @param key 键
     * @param value 值
     * @param ttl 过期时间（毫秒）
     */
    set(key: K, value: V, ttl?: number): void {
        // 如果缓存已满，删除最旧的项
        if (this.cache.size >= this.maxItems) {
            const firstKey = this.cache.keys().next().value;
            if (firstKey) {
                this.cache.delete(firstKey);
            }
        }

        // 计算过期时间
        const expiry = ttl || this.defaultTTL
            ? Date.now() + (ttl || this.defaultTTL!)
            : undefined;

        this.cache.set(key, { value, expiry });
    }

    /**
     * 删除缓存项
     * @param key 键
     */
    delete(key: K): void {
        this.cache.delete(key);
    }

    /**
     * 清空缓存
     */
    clear(): void {
        this.cache.clear();
    }

    /**
     * 获取缓存大小
     */
    size(): number {
        this.removeExpired();
        return this.cache.size;
    }

    /**
     * 检查键是否存在
     * @param key 键
     */
    has(key: K): boolean {
        const item = this.cache.get(key);
        if (!item) return false;

        if (item.expiry && item.expiry < Date.now()) {
            this.cache.delete(key);
            return false;
        }

        return true;
    }

    /**
     * 移除过期的缓存项
     */
    private removeExpired(): void {
        const now = Date.now();
        for (const [key, item] of this.cache.entries()) {
            if (item.expiry && item.expiry < now) {
                this.cache.delete(key);
            }
        }
    }
}
